 /**
 *  
 * This is a form dijit that can be used inside a form and it let you select a host or a folder from your dotCMS instance, the selected host/folder id will
 * be send in the form based on the name attribute you set for your dijit.
 * 
 * To include the dijit into your page
 * 
 * JS Side
 * 
 * <script type="text/javascript">
 * 	dojo.require("dotcms.dijit.form.HostFolderFilteringSelect");
 * 
 * ...
 * 
 * </script>
 * 
 * HTML side
 * 
 * <div id="myDijitId" jsId="myJSVariable" style="cssStyleOptions" name="myNameWithinTheForm" onlySelectFolders="true" value="folder/host id" dojoType="dotcms.dijit.form.HostFolderFilteringSelect"></div>
 * 
 * Properties
 * 
 * id: non-required - this is the id of the widget if not specified then it will be autogenerated.
 * 
 * jsId: non-required - if specified then dijit will be registered in the JS global enviroment with this name.
 * 
 * name: non-required - Need to be specified if you want the selected folder/host id to be submitted with your form.
 * 
 * onlySelectFolders: non-required - default false - Let you specify if you want to disable the ability to select hosts and only allow folders to be selected.
 * 
 * value: The id of the folder or host you want the widget to preselect.
 * 
 * style: non-required - modifies the html css styles of the combo box.
 * 
 * Programattically
 *  
 * How to retrieve values from the dijit
 * 
 * To retrieve the selected folder/host id 
 * dijit.byId('myDijitId').attr('value') // Will return something like '6fa459ea-ee8a-3ca4-894e-db77e160355e'
 * 
 * To retrieved the name of the selected host/folder
 * dijit.byId('myDijitId').attr('displayedValue')  // Will return something like 'applications'
 * 
 * To retrieved the selected host/folder js object
 * dijit.byId('myDijitId').attr('selectedItem') //Will return a js object like { id: '6fa459ea-ee8a-3ca4-894e-db77e160355e', name: 'applications', type:'folder' }
 * 
 * How to set a value
 *  
 * dijit.byId('myDijitId').attr('value', 'IdOfTheFolderHost')
 * 
 * If the IdOfTheFolderHost doesn't exists the dijit will ignore the request
 * 
 */

dojo.provide("dotcms.dijit.form.HostFolderFilteringSelect");

dojo.require("dijit._Widget");
dojo.require("dijit._Templated");
dojo.require("dojox.data.JsonRestStore")
dojo.require("dijit.tree.TreeStoreModel")
dojo.require("dijit.Tree")

dojo.declare("dotcms.dijit.form.HostFolderFilteringSelect", [dijit._Widget, dijit._Templated], {
	
	templatePath: dojo.moduleUrl("dotcms", "dijit/form/HostFolderFilteringSelect.html"),

	name: "",
	value: "",
	displayedValue: "",
	selectedItem: "",
	style: "width:348px;",
	onlySelectFolders: false,
	targetUrl: '',
	postCreate: function (elem) {
	
		var url = dojo.moduleUrl("dotcms", "dijit/form/HostFolderFilteringSelectTree.html")
		var templateString = dojo._getText(url);
		var html = dojo.string.substitute(templateString, { id: this.id })
        var domObj = dojo._toDom(html);
		dojo.place(domObj, this.id, 'last');
		this.hostFoldersTreeWrapper = dojo.byId(this.id + '-hostFoldersTreeWrapper');
		this.hostFoldersTree = dojo.byId(this.id + '-hostFoldersTree');
		
	
		var boxDim = dojo.contentBox(this.hostFolderComboBox);
		dojo.style(this.hostFoldersTreeWrapper, { width: (boxDim.w -37) + "px" });
		
		/*
		 * Ajax call to retrieve tree data 
		 */
		//BrowserAjax.getTreeMinInfo({ callback: this.postCreateCallback, scope: this });
		this.bodyClickHandle = dojo.connect(dojo.body(), 'onclick', this, this._onBodyClick);
		//Hide the original div.
		dojo.style(this.hostFoldersTreeWrapper, {display: 'none'});
	},
	
	postCreateCallback: function(treeData) {
		this.treeData = treeData;
		            
        var store = new dojox.data.JsonRestStore( {
				labelAttribute: 'name',
				idAttribute: 'inode',
                target: this.targetUrl});

        var model = new dijit.tree.ForestStoreModel( {
			store: store,
			deferItemLoadingUntilExpand: true,
			query: "root",
			mayHaveChildren: function(item){
				var had = (item === this.root);
				if(!had) {
					return dojo.some(['hasChildren', 'children'], function(attr){
						return this.store.hasAttribute(item, attr);
					}, this);
				}
				return had;
			},
            showRoot: false
		});
		this.tree = new dijit.Tree( {
			model: model,
            id: "MenuTree"});
		this.tree.placeAt(this.hostFoldersTreeWrapper);

		dojo.connect(this.tree, 'onClick', this, this._selectItem);
		
		this._flattenTree(treeData);
		/**
		if(this.value != '') {
			var selectedHostFolder = this._findFolder(this.value, this.flatTree);
			if(selectedHostFolder)
				this._selectItem(selectedHostFolder);
			else 
				this.value = "";
			
		}
		**/
	},
	
	uninitialize : function (event) {
		dojo.disconnect(this.bodyClickHandle);
	},
	
	showHideHostFolderList: function (event) {
		this.filter = '';
		var display = dojo.style(this.hostFoldersTreeWrapper, 'display');
		if(display == '' || display == 'block') {
			dojo.style(this.hostFoldersTreeWrapper, { display: 'none' });
		} else {
			this._repositionTreeWrapper();
			dojo.style(this.hostFoldersTreeWrapper, { display: '' });
		}
	},
	
	/**
	 * Stub method that you can use dojo.connect to catch every time a user selects a folder from the tree
	 * @param {Object} item
	 */
	itemSelected: function (item) {
		
	},
	
	filterTree : function (event) {
		if(this.filterTreeDefHandler)
			clearTimeout(this.filterTreeDefHandler);
		this.filterTreeDefHandler = setTimeout(dojo.hitch(this, this._filterTreeDef), 500);

		this.attr('value', null); 
		this.attr('displayedValue', null); 
		this.attr('selectedItem', null); 
		this.hostFolderSelectedId.value = '';

	},
		
	_repositionTreeWrapper: function() {
		var selectCoords = dojo.coords(this.hostFileFilteringSelectWrapper, true);
		dojo.style(this.hostFoldersTreeWrapper, { left: selectCoords.x, top: (selectCoords.y + selectCoords.h)});
	},
	
	_filterTreeDef : function (event) {

		var query = this.hostFolderSelectedName.value;

		if(query == '') {
			for(var i = 0; i < this.flatTree.length; i++) {
				var folder = this.flatTree[i];
				var treeNode = dojo.byId(this.id + '-tree-treeNode-' + this._norm(folder.id))
				if(treeNode)
					dojo.style(treeNode, { display: ''})
			}
			return;	
		}

		var folders = this._searchFolders(query, this.flatTree);
		var branches = this._getFoldersFlatUpBranches(folders);

		for(var i = 0; i < this.flatTree.length; i++) {
			var folder = this.flatTree[i];
			var folderId = this._norm(folder.id);
			var treeNode = dojo.byId(this.id + '-tree-treeNode-' + folderId)
			if(treeNode) {
				if(!this._findFolder(folderId, branches)) {
					dojo.style(treeNode, { display: 'none'});
					var dijitNode = dijit.byId(treeNode.id);
				} else {
					dojo.style(treeNode, { display: ''});
					var dijitNode = dijit.byId(treeNode.id);
					this.tree._expandNode(dijitNode)
				}
			}
		}
		
		var display = dojo.style(this.hostFoldersTreeWrapper, 'display');
		if(display == 'none') {
			this._repositionTreeWrapper();
			dojo.style(this.hostFoldersTreeWrapper, { display: '' });
		}

	},
	
	_searchFolders: function(query, folders){
		var matches = [];
		for (var i = 0; i < folders.length; i++) {
			var folderName = this._norm(folders[i].name);
			var regexQuery = new RegExp(query, "i");
			if (folderName.match(regexQuery)) 
				matches.push(folders[i]);
		}
		return matches;
	},
	
	_flattenTree: function (tree){
		this.flatTree = [];
		this._flattenTreeRec(null, tree);
	},
	
	_flattenTreeRec: function  (treeParent, tree) {
		for(var i = 0; i < tree.length; i++) {
			var node = tree[i];
			node.parent = treeParent;
			this.flatTree.push(node);
			if (node.children)
				this._flattenTreeRec(node, node.children);
		}
	},
	
	_getFoldersFlatUpBranches: function (folders) {
		
		var branches = []
		
		for(var i = 0; i < folders.length; i++) {
			var folder = folders[i];
			branches.push(folder);
			
			if(folder.parent)
				var parentId = this._norm(folder.parent.id);
			else
				var parentId = null; 
			var id = this._norm(folder.id);
	
			while(parentId && parentId != id) {
				folder = this._findFolder(parentId, this.flatTree);
				branches.push(folder);
				if(folder.parent)
					var parentId = this._norm(folder.parent.id);
				else
					var parentId = null; 
				var id = this._norm(folder.id);						
			}

		}
		return branches;
	},
	
	_findFolder: function (id, folders) {
		for(var i = 0; i < folders.length; i++) {
			var idIt = this._norm(folders[i].id);
			id = this._norm(id);
			if(id == idIt)
				return folders[i];
		}
		return null;
	},
	
	_norm: function (value) {
		return dojo.isArray(value)?value[0]:value;
	},	
	
	onChange: function(newValue) { },
	
	_selectItem: function(item, event) { 
		if(this.onlySelectFolders && this._norm(item.type) != 'folder')
			return false;
		this.value = this._norm(item.name); 
		this.displayedValue = this._norm(item.name); 
		this.selectedItem = item; 
		this.hostFolderSelectedName.value = this._norm(item.name);
		this.hostFolderSelectedId.value = this._norm(item.inode);
		dojo.style(this.hostFoldersTreeWrapper, { display: 'none' });
		this.itemSelected(item);
		this.onChange(item);
		return true;
	},	
	
	_onBodyClick: function (event) {
		if(!this._within(event, this.hostFoldersTreeWrapper) && 
			!this._within(event, this.hostFileFilteringSelectWrapper)) {
			dojo.style(this.hostFoldersTreeWrapper, {
				display: 'none'
			});
		} else {
			if(!this.tree) {
				this.postCreateCallback(new Array());
			}
			this._repositionTreeWrapper();
			dojo.style(this.hostFoldersTreeWrapper, {
				display: 'block'
			});
		}
	},
	
	_within: function (event, elem) {
		var x = event.clientX;
		var y = event.clientY;
		var coords = dojo.coords(elem);
		
		if(x < coords.x || x > coords.x + coords.w || y < coords.y || y > coords.y + coords.h) {
			return false;
		}
		return true;		
	},
	
	_setValueAttr: function(/*String*/ value) {
		if(!this.flatTree) return;
		var selectedHostFolder = this._findFolder(value, this.flatTree);
		if(selectedHostFolder)
			this._selectItem(selectedHostFolder);
		else 
			this.value = "";
	}
	
})